﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
using School.Entities;

namespace School.Common
{
    public static class Finance
    {
        private static SchoolEntities db = new SchoolEntities();

        public static IEnumerable<DiscountObject> GetDiscounts(string screen, long campus = 0, long certificate = 0, long stage = 0, long grade = 0, long father_job = 0, long father_status = 0, long mother_job = 0, long mother_status = 0, int brothers = 0, int order = 0, long studentId = 0)
        {
            var expenses = from x in db.ACC_Expenses_Screens where x.Screen_Id == (from y in db.SEC_Screen where y.Code == screen select y.Id).FirstOrDefault() select x.Expense_Id;

            if (expenses.Count() != 0)
            {
                var discounts = from x in db.ACC_Discount where (from y in db.ACC_Expense_Discount where expenses.Contains(y.Expense_Id) select y.Discount_Id).Contains(x.Id) select x;

                List<ACC_Discount> whole = new List<ACC_Discount>();

                if (studentId != 0)
                {
                    campus = db.TE_Student.Single(x => x.Id == studentId).Campus_Id;
                    certificate = db.TE_Student.Single(x => x.Id == studentId).Certificate_Id;
                    stage = db.TE_Student.Single(x => x.Id == studentId).Stage_Id;
                    grade = db.TE_Student.Single(x => x.Id == studentId).Grade_ID;
                }

                if (campus != 0)
                {
                    whole.AddRange(discounts.Where(x => (from y in db.ACC_Discount_Campus where y.Campus_Id == campus select y.Discount_Id).Contains(x.Id)));
                    whole.AddRange(discounts.Where(x => (from y in db.ACC_Discount_Certificate where y.ORG_Certificate.Campus_Id == campus select y.Discount_Id).Contains(x.Id)));
                    whole.AddRange(discounts.Where(x => (from y in db.ACC_Discount_Stage where y.ORG_Stage.ORG_Certificate.Campus_Id == campus select y.Discount_Id).Contains(x.Id)));
                    whole.AddRange(discounts.Where(x => (from y in db.ACC_Discount_Grade where y.ORG_Grade.ORG_Stage.ORG_Certificate.Campus_Id == campus select y.Discount_Id).Contains(x.Id)));
                }

                if (certificate != 0)
                {
                    whole.AddRange(discounts.Where(x => (from y in db.ACC_Discount_Certificate where y.Certificate_Id == certificate select y.Discount_Id).Contains(x.Id)));
                    whole.AddRange(discounts.Where(x => (from y in db.ACC_Discount_Stage where y.ORG_Stage.Certificate_Id == certificate select y.Discount_Id).Contains(x.Id)));
                    whole.AddRange(discounts.Where(x => (from y in db.ACC_Discount_Grade where y.ORG_Grade.ORG_Stage.Certificate_Id == certificate select y.Discount_Id).Contains(x.Id)));
                }

                if (stage != 0)
                {
                    whole.AddRange(discounts.Where(x => (from y in db.ACC_Discount_Stage where y.Stage_Id == stage select y.Discount_Id).Contains(x.Id)));
                    whole.AddRange(discounts.Where(x => (from y in db.ACC_Discount_Grade where y.ORG_Grade.Stage_Id == stage select y.Discount_Id).Contains(x.Id)));
                }

                if (grade != 0)
                {
                    whole.AddRange(discounts.Where(x => (from y in db.ACC_Discount_Grade where y.Grade_Id == grade select y.Discount_Id).Contains(x.Id)));
                }

                if (whole.Count() == 0)
                    whole.AddRange(discounts);

                var all = whole.Distinct();

                List<DiscountObject> rows = new List<DiscountObject>();

                var n = all.Select(z => z.Id);

                if (father_job != 0)
                {
                    var fj = from x in db.ACC_Discount_Fahter_Job where n.Contains(x.Discount_Id) && x.Father_Job_Id == father_job select x;

                    if (fj.Count() > 0)
                    {
                        foreach (var d in fj)
                        {
                            rows.Add(new DiscountObject() { Name = d.ACC_Discount.Name, Id = d.Discount_Id, Type = d.Type, Value = d.Value });
                        }
                    }
                }

                if (mother_job != 0)
                {
                    var mj = from x in db.ACC_Discount_Mother_Job where n.Contains(x.Discount_Id) && x.Mother_Job_Id == mother_job select x;

                    if (mj.Count() > 0)
                    {
                        foreach (var d in mj)
                        {
                            rows.Add(new DiscountObject() { Name = d.ACC_Discount.Name, Id = d.Discount_Id, Type = d.Type, Value = d.Value });
                        }
                    }
                }

                if (father_status != 0)
                {
                    var fs = from x in db.ACC_Discount_Father_Status where n.Contains(x.Discount_Id) && x.Father_Status_Id == father_status select x;

                    if (fs.Count() > 0)
                    {
                        foreach (var d in fs)
                        {
                            rows.Add(new DiscountObject() { Name = d.ACC_Discount.Name, Id = d.Discount_Id, Type = d.Type, Value = d.Value });
                        }
                    }
                }

                if (mother_status != 0)
                {
                    var ms = from x in db.ACC_Discount_Mother_Status where n.Contains(x.Discount_Id) && x.Mother_Status == mother_status select x;

                    if (ms.Count() > 0)
                    {
                        foreach (var d in ms)
                        {
                            rows.Add(new DiscountObject() { Name = d.ACC_Discount.Name, Id = d.Discount_Id, Type = d.Type, Value = d.Value });
                        }
                    }
                }

                if (brothers != 0)
                {
                    var br = from x in db.ACC_Discount_Brothers where n.Contains(x.Discount_Id) && x.Brothers_Number == brothers select x;

                    if (br.Count() > 0)
                    {
                        foreach (var d in br)
                        {
                            rows.Add(new DiscountObject() { Name = d.ACC_Discount.Name, Id = d.Discount_Id, Type = d.Type, Value = d.Value });
                        }
                    }
                }

                if (order != 0)
                {
                    var so = from x in db.ACC_Discount_Student_Order where n.Contains(x.Discount_Id) && x.Student_Order == order select x;

                    if (so.Count() > 0)
                    {
                        foreach (var d in so)
                        {
                            rows.Add(new DiscountObject() { Name = d.ACC_Discount.Name, Id = d.Discount_Id, Type = d.Type, Value = d.Value });
                        }
                    }
                }

                var ot = from x in db.ACC_Discount_Others where n.Contains(x.Discount_Id) select x;

                if (ot.Count() > 0)
                    foreach (var d in ot)
                    {
                        rows.Add(new DiscountObject() { Name = d.ACC_Discount.Name, Id = d.Discount_Id, Type = d.Type, Value = d.Value });
                    }

                return rows;
            }
            else
                return null;
        }

        public static IEnumerable<DiscountObject> GetExpenseDiscounts(long expense, long campus = 0, long certificate = 0, long stage = 0, long grade = 0, long father_job = 0, long father_status = 0, long mother_job = 0, long mother_status = 0, int brothers = 0, int order = 0, long studentId = 0, decimal value = 0)
        {
            var expenses = from x in db.ACC_Expense where x.ID == expense select x.ID;

            if (expenses.Count() != 0)
            {
                var discounts = from x in db.ACC_Discount where (from y in db.ACC_Expense_Discount where expenses.Contains(y.Expense_Id) select y.Discount_Id).Contains(x.Id) select x;

                List<ACC_Discount> whole = new List<ACC_Discount>();

                if (studentId != 0)
                {
                    campus = db.TE_Student.Single(x => x.Id == studentId).Campus_Id;
                    certificate = db.TE_Student.Single(x => x.Id == studentId).Certificate_Id;
                    stage = db.TE_Student.Single(x => x.Id == studentId).Stage_Id;
                    grade = db.TE_Student.Single(x => x.Id == studentId).Grade_ID;
                }

                if (campus != 0)
                {
                    whole.AddRange(discounts.Where(x => (from y in db.ACC_Discount_Campus where y.Campus_Id == campus select y.Discount_Id).Contains(x.Id)));
                    whole.AddRange(discounts.Where(x => (from y in db.ACC_Discount_Certificate where y.ORG_Certificate.Campus_Id == campus select y.Discount_Id).Contains(x.Id)));
                    whole.AddRange(discounts.Where(x => (from y in db.ACC_Discount_Stage where y.ORG_Stage.ORG_Certificate.Campus_Id == campus select y.Discount_Id).Contains(x.Id)));
                    whole.AddRange(discounts.Where(x => (from y in db.ACC_Discount_Grade where y.ORG_Grade.ORG_Stage.ORG_Certificate.Campus_Id == campus select y.Discount_Id).Contains(x.Id)));
                }

                if (certificate != 0)
                {
                    whole.AddRange(discounts.Where(x => (from y in db.ACC_Discount_Certificate where y.Certificate_Id == certificate select y.Discount_Id).Contains(x.Id)));
                    whole.AddRange(discounts.Where(x => (from y in db.ACC_Discount_Stage where y.ORG_Stage.Certificate_Id == certificate select y.Discount_Id).Contains(x.Id)));
                    whole.AddRange(discounts.Where(x => (from y in db.ACC_Discount_Grade where y.ORG_Grade.ORG_Stage.Certificate_Id == certificate select y.Discount_Id).Contains(x.Id)));
                }

                if (stage != 0)
                {
                    whole.AddRange(discounts.Where(x => (from y in db.ACC_Discount_Stage where y.Stage_Id == stage select y.Discount_Id).Contains(x.Id)));
                    whole.AddRange(discounts.Where(x => (from y in db.ACC_Discount_Grade where y.ORG_Grade.Stage_Id == stage select y.Discount_Id).Contains(x.Id)));
                }

                if (grade != 0)
                {
                    whole.AddRange(discounts.Where(x => (from y in db.ACC_Discount_Grade where y.Grade_Id == grade select y.Discount_Id).Contains(x.Id)));
                }

                if (whole.Count() == 0)
                    whole.AddRange(discounts);

                var all = whole.Distinct();

                List<DiscountObject> rows = new List<DiscountObject>();

                var n = all.Select(z => z.Id);

                if (father_job != 0)
                {
                    var fj = from x in db.ACC_Discount_Fahter_Job where n.Contains(x.Discount_Id) && x.Father_Job_Id == father_job select x;

                    if (fj.Count() > 0)
                    {
                        foreach (var d in fj)
                        {
                            if(d.Type == 2)
                                rows.Add(new DiscountObject() { Name = d.ACC_Discount.Name, Id = d.Discount_Id, Type = d.Type, Value = value > 0 ? (d.Value / 100) * value : d.Value });
                            else
                                rows.Add(new DiscountObject() { Name = d.ACC_Discount.Name, Id = d.Discount_Id, Type = d.Type, Value = d.Value });
                        }
                    }
                }

                if (mother_job != 0)
                {
                    var mj = from x in db.ACC_Discount_Mother_Job where n.Contains(x.Discount_Id) && x.Mother_Job_Id == mother_job select x;

                    if (mj.Count() > 0)
                    {
                        foreach (var d in mj)
                        {
                            if (d.Type == 2)
                                rows.Add(new DiscountObject() { Name = d.ACC_Discount.Name, Id = d.Discount_Id, Type = d.Type, Value = value > 0 ? (d.Value / 100) * value : d.Value });
                            else
                                rows.Add(new DiscountObject() { Name = d.ACC_Discount.Name, Id = d.Discount_Id, Type = d.Type, Value = d.Value });
                        }
                    }
                }

                if (father_status != 0)
                {
                    var fs = from x in db.ACC_Discount_Father_Status where n.Contains(x.Discount_Id) && x.Father_Status_Id == father_status select x;

                    if (fs.Count() > 0)
                    {
                        foreach (var d in fs)
                        {
                            if (d.Type == 2)
                                rows.Add(new DiscountObject() { Name = d.ACC_Discount.Name, Id = d.Discount_Id, Type = d.Type, Value = value > 0 ? (d.Value / 100) * value : d.Value });
                            else
                                rows.Add(new DiscountObject() { Name = d.ACC_Discount.Name, Id = d.Discount_Id, Type = d.Type, Value = d.Value });
                        }
                    }
                }

                if (mother_status != 0)
                {
                    var ms = from x in db.ACC_Discount_Mother_Status where n.Contains(x.Discount_Id) && x.Mother_Status == mother_status select x;

                    if (ms.Count() > 0)
                    {
                        foreach (var d in ms)
                        {
                            if (d.Type == 2)
                                rows.Add(new DiscountObject() { Name = d.ACC_Discount.Name, Id = d.Discount_Id, Type = d.Type, Value = value > 0 ? (d.Value / 100) * value : d.Value });
                            else
                                rows.Add(new DiscountObject() { Name = d.ACC_Discount.Name, Id = d.Discount_Id, Type = d.Type, Value = d.Value });
                        }
                    }
                }

                if (brothers != 0)
                {
                    var br = from x in db.ACC_Discount_Brothers where n.Contains(x.Discount_Id) && x.Brothers_Number == brothers select x;

                    if (br.Count() > 0)
                    {
                        foreach (var d in br)
                        {
                            if (d.Type == 2)
                                rows.Add(new DiscountObject() { Name = d.ACC_Discount.Name, Id = d.Discount_Id, Type = d.Type, Value = value > 0 ? (d.Value / 100) * value : d.Value });
                            else
                                rows.Add(new DiscountObject() { Name = d.ACC_Discount.Name, Id = d.Discount_Id, Type = d.Type, Value = d.Value });
                        }
                    }
                }

                if (order != 0)
                {
                    var so = from x in db.ACC_Discount_Student_Order where n.Contains(x.Discount_Id) && x.Student_Order == order select x;

                    if (so.Count() > 0)
                    {
                        foreach (var d in so)
                        {
                            if (d.Type == 2)
                                rows.Add(new DiscountObject() { Name = d.ACC_Discount.Name, Id = d.Discount_Id, Type = d.Type, Value = value > 0 ? (d.Value / 100) * value : d.Value });
                            else
                                rows.Add(new DiscountObject() { Name = d.ACC_Discount.Name, Id = d.Discount_Id, Type = d.Type, Value = d.Value });
                        }
                    }
                }

                var ot = from x in db.ACC_Discount_Others where n.Contains(x.Discount_Id) select x;

                if (ot.Count() > 0)
                    foreach (var d in ot)
                    {
                        if (d.Type == 2)
                            rows.Add(new DiscountObject() { Name = d.ACC_Discount.Name, Id = d.Discount_Id, Type = d.Type, Value = value > 0 ? (d.Value / 100) * value : d.Value });
                        else
                            rows.Add(new DiscountObject() { Name = d.ACC_Discount.Name, Id = d.Discount_Id, Type = d.Type, Value = d.Value });
                    }


                return rows;
            }
            else
                return null;
        }
    }

    public class DiscountObject
    {
        public string Name { set; get; }
        public long Id { set; get; }
        public byte Type { set; get; }
        public decimal Value { set; get; }
    }
}
